package org.dahuatech.ssh.service.account;

import java.util.List;
import java.util.Map;
import java.util.Set;

import org.dahuatech.ssh.common.orm.Page;
import org.dahuatech.ssh.common.orm.PropertyFilter;
import org.dahuatech.ssh.dao.account.AuthorityDao;
import org.dahuatech.ssh.dao.account.RoleDao;
import org.dahuatech.ssh.dao.account.UserDao;
import org.dahuatech.ssh.entity.account.Authority;
import org.dahuatech.ssh.entity.account.Role;
import org.dahuatech.ssh.entity.account.User;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;

/**
 * 安全相关实体的管理类, 包括用户,角色,资源与授权类.
 * 
 * @author calvin
 */
//Spring Bean的标识.
@Service
//默认将类中的所有函数纳入事务管理.
@Transactional
public class AccountManager {

	private static Logger logger = LoggerFactory.getLogger(AccountManager.class);

	private UserDao userDao;
	private RoleDao roleDao;
	private AuthorityDao authorityDao;
	

	//-- User Manager --//
	@Transactional(readOnly = true)
	public User getUser(Long id) {
		return userDao.get(id);
	}
	
	@Transactional(readOnly=true)
	public Authority getAuthority(Long id){
	    return authorityDao.get(id);
	}
	
	@Transactional
	public void deleteAuthorotity(Long id){
	    authorityDao.delete(id);
	}

	public void saveUser(User entity) {
		userDao.save(entity);
	}

	/**
	 * 删除用户,如果尝试删除超级管理员将抛出异常.
	 */
	public void deleteUser(Long id) {
		if (isSupervisor(id)) {
			logger.warn("尝试删除超级管理员用户错误");
		}
		userDao.delete(id);
	}

	/**
	 * 判断是否超级管理员.
	 */
	private boolean isSupervisor(Long id) {
		return id == 1;
	}

	/**
	 * 使用属性过滤条件查询用户.
	 */
	@Transactional(readOnly = true)
	public Page<User> searchUser(final Page<User> page, final List<PropertyFilter> filters) {
		return userDao.findPage(page, filters);
	}

	@Transactional(readOnly = true)
	public User findUserByLoginName(String loginName) {
		return userDao.findUniqueBy("loginName", loginName);
		//return userDao.findUnique("from User u where u.loginName=? and u.password=?", values)
	}
	
	@Transactional(readOnly=true)
	public User findUser(User user){
		return userDao.findUnique("from User u where u.loginName=? and u.password=?", user.getLoginName(),user.getPassword());
	}
	
	@Transactional(readOnly=true)
	public Map<Long,Authority> getAuthorityMenuItem(User user){
		List<Authority> authorities=Lists.newArrayList();
		if("admin".equals(user.getLoginName())){
		    authorities = authorityDao.listAllAuthorities();
		}else{
		    authorities = authorityDao.listAllAuthorities(user.getId());
		}
		return generateAuthorizedMenus(authorities);
	}
	
	@Transactional(readOnly=true)
	public Set<Authority> getAuthoritiesByIds(List<Long> ids){
	    List<Authority> list=authorityDao.listAuthoritiesByIds(ids);
	    Set<Authority> authorities=Sets.newHashSet();
	    for(Authority authority:list){
	        authorities.add(authority);
	    }
	    return authorities;
	}
	
	@Transactional
	public void saveAuthority(Authority authority){
	    authorityDao.save(authority);
	}
	
	/**
	 * 把菜单生成树
	 * @param list
	 * @return
	 */
	private Map<Long,Authority> generateAuthorizedMenus(List<Authority> list){
		Map<Long,Authority> maps=Maps.newTreeMap();
		for(Authority authority:list){
		    Authority rootAuthorityItem=maps.get(authority.getpId());
			if(rootAuthorityItem==null){
				maps.put(authority.getId(), authority);
			}else{
			    rootAuthorityItem.getChildAuthorities().put(authority.getId(), authority);
			}
		}
		return maps;
	}

	/**
	 * 检查用户名是否唯一.
	 *
	 * @return loginName在数据库中唯一或等于oldLoginName时返回true.
	 */
	@Transactional(readOnly = true)
	public boolean isLoginNameUnique(String newLoginName, String oldLoginName) {
		return userDao.isPropertyUnique("loginName", newLoginName, oldLoginName);
	}

	//-- Role Manager --//
	@Transactional(readOnly = true)
	public Role getRole(Long id) {
		return roleDao.get(id);
	}

	@Transactional(readOnly = true)
	public List<Role> getAllRole() {
		return roleDao.getAll("id", true);
	}

	public void saveRole(Role entity) {
		roleDao.save(entity);
	}

	public void deleteRole(Long id) {
		roleDao.delete(id);
	}

	//-- Authority Manager --//
	@Transactional(readOnly = true)
	public List<Authority> getAllAuthority() {
		return authorityDao.getAll();
	}

	@Autowired
	public void setUserDao(UserDao userDao) {
		this.userDao = userDao;
	}

	@Autowired
	public void setRoleDao(RoleDao roleDao) {
		this.roleDao = roleDao;
	}

	@Autowired
	public void setAuthorityDao(AuthorityDao authorityDao) {
		this.authorityDao = authorityDao;
	}

}
